from parse.AST.program import Program
from parse.symbol_table.function import Function
from parse.AST.statement import Statement
from parse.AST.assign_statment import AssignStatment
from parse.AST.func_call_statement import FuncCallStatement
from parse.symbol_table.function import Function
from parse.symbol_table.variable import Variable
from parse.symbol_table.pointer import Pointer
from parse.symbol_table.array import Array
from parse.symbol_table.constant_variable import ConstantVariable

class Generator:
    def __init__(self, program: Program, file):
        self.program = program
        self.file = file

    def generateAsm(self):
        for func in self.program.functionList:
            self.generateFunction(func)

    def generateFunction(self, func: Function):
        # 为了方便输出，这里使用了C语言的printf函数
        # 为了让程序正常结束执行，用了C语言的_exit函数
        self.file.write("extern _printf, _exit")

        for statement in func.statementList:
            self.generateStatement(statement)

        # 这里为了方便判断程序运行的结果，就把返回值(从rax中读取)
        # 打印到标准输出
        self.file.write("mov rdi, \"%d\"\n")
        self.file.write("mov rsi, rax\n")
        self.file.write("call _printf\n")

        # 程序执行结束，exit
        self.file.write("mov rdi, 0\n")
        self.file.write("call _exit\n")

    def generateStatement(self, statement: Statement):
        if isinstance(statement, AssignStatment):
            self.generateAssignStatement(statement)
        elif isinstance(statement, FuncCallStatement):
            self.generateFuncCallStatement(statement)

    def generateAssignStatement(self, statement: AssignStatment):
        # 因为变量是存在栈中，也就是内存中，汇编不支持 内存->内存
        # 的操作，所以要先把等号右边的值放到寄存器，然后再把寄存器
        # 中的值放到等号左边
        if statement.right.offset == 0:
            self.file.write("mov rax, @var_%s\n".format(statement.right.name))
        else:
            self.file.write("mov rax, [rbp+%d]\n".format(statement.right.offset))

        if statement.left.offset == 0:
            self.file.write("mov @var_%s, rax\n".format(statement.left.name))
        else:
            self.file.write("mov [rbp+%d], rax\n".format(statement.left.offset))

    def generateFuncCallStatement(self, statement: FuncCallStatement):
        pass

